import axios from 'axios'
import NProgress from 'nprogress' // Progress 进度条
import 'nprogress/nprogress.css' // Progress 进度条样式

const ERROR_MAP = {
  30002: {msg: '文件不存在！'},
  30003: {msg: '文件不是excel文件！'},
  30005: {msg: '请上传正确的用户UM号文件'},
  50003: {msg: '请重新登陆'},
  50004: {msg: '用户名不存在'},
  50005: {msg: '密码错误'},
  50006: {msg: '您暂无此权限'},
  50007: {msg: '您不是该系统用户'},
  60001: {msg: '上个文件正在上传中，请稍后。'},
  70001: {msg: '请上传正确的基础标签文件!'}
}

export default {
  // 自定义判断元素类型JS
  toType: function (obj) {
    return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
  },
  // 参数过滤函数
  /**
   * @deprecated
   * @param method
   * @param url
   * @param params
   * @param data
   * @returns {Promise<unknown>}
   */
  $apiAxios: function (method, url, params = {}, data = null) {
    NProgress.start()
    const self = this

    let loadingInstance = null
    if (params.loading) {
      loadingInstance = this.$loading({fullscreen: false, text: '请求数据中，请等待！', target:document.querySelector('#content-wrapper')})
      delete (params.loading)
    }

    if (method === 'GET' || method === 'DELETE') {
      let time = new Date().getTime()
      if (url.indexOf('?') > -1) {
        url = url + '&_t=' + time
      } else {
        url = url + '?_t=' + time
      }
    }

    if (method === 'POST' || method === 'PUT') {
      let time = new Date().getTime()
      params = Object.assign({}, params, {_t: time})
    }
    
    const options = {
      'method': method,
      'url': url,
      'params': params,
      'data': data,
      'baseURL': self.getHost(),
      'withCredentials': true
    }

    return new Promise((resolve, reject) => {
      axios.defaults.withCredentials = true
      if (method == 'POST' || method == 'PUT') {
        axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded'
      }
      axios(options).then(function (res) {
        NProgress.done()
        if (loadingInstance) {
          loadingInstance.close()
        }
        if (!res.data.code) {
          resolve && resolve(res.data.data)
        } else {
          self._doErrorCode(res)
          reject && reject(res.data)
        }
      }).catch(function (error) {
        NProgress.done()
        if (loadingInstance) {
          loadingInstance.close()
        }
        if (error.response) {
          // The request was made, but the server responded with a status code
          // that falls out of the range of 2xx
          // console.log(error.response.data)
          // console.log(error.response.status)
          // console.log(error.response.headers)
          let code = error.response.data.code ? error.response.data.code : null
          let msg = `系统错误 => data: ${error.response.data}, status: ${error.response.status}, headers${error.response.headers}|请联系技术人员`
          if (code) {
            self.$message.error(ERROR_MAP[code].msg)
            if (code == 50003) {
              self.toLogin()
            }
            return
          }
          self.$message.error(msg)
        } else {
          // Something happened in setting up the request that triggered an Error
          console.log('Error', error.message)
          self.$message.error(`系统错误 => ${error.message}|请联系技术人员`)
        }
      })
    })
  },
  $apiAxios2: function (method, url, params = {}) {
    NProgress.start()
    const self = this

    let loadingInstance = null
    if (params.loading) {
      loadingInstance = this.$loading({fullscreen: false, text: '请求数据中，请等待！',
      target:document.querySelector('#content-wrapper')})
      delete (params.loading)
    }

    const options = {
      'method': method,
      'url': url,
      'params': method === 'GET' || method === 'DELETE' ? params : null,
      'data': method === 'POST' || method === 'PUT' ? params : null,
      'baseURL': process.env.API_HOST,
      'withCredentials': true,
      'headers': {'Content-Type': 'application/json;charset=UTF-8'}
    }

    return new Promise((resolve, reject) => {
      axios.defaults.withCredentials = true
      axios(options).then(function (res) {
        NProgress.done()
        if (loadingInstance) {
          loadingInstance.close()
        }
        resolve && resolve(res.data)
      }).catch(function (error) {
        NProgress.done()
        if (loadingInstance) {
          loadingInstance.close()
        }
        if (error.response) {
          // The request was made, but the server responded with a status code
          // that falls out of the range of 2xx
          // console.log(error.response.data)
          // console.log(error.response.status)
          // console.log(error.response.headers)
          let msg = `系统错误 => data: ${error.response.data}, status: ${error.response.status}, headers${error.response.headers}|请联系技术人员`
          self.$message.error(msg)
        } else {
          // Something happened in setting up the request that triggered an Error
          console.log('Error', error.message)
          self.$message.error(`系统错误 => ${error.message}|请联系技术人员`)
        }
      })
    })
  },
  _doErrorCode (res) {
    let code = res.data.code ? res.data.code : null
    if (code) {
      if (ERROR_MAP[code] || res.data.msg) {
        let msg = res.data.msg ? res.data.msg : ERROR_MAP[code].msg
        this.$message.error(msg)
        if (code == 50003) {
          this.toLogin()
        }
      } else {
        this.$message.error(`系统错误 => 未知错误：${code}`)
      }
    }
  },
  /*
   接口处理函数
   这个函数每个项目都是不一样的，我现在调整的是适用于
   https://cnodejs.org/api/v1 的接口，如果是其他接口
   需要根据接口的参数进行调整。参考说明文档地址：
   https://cnodejs.org/topic/5378720ed6e2d16149fa16bd
   主要是，不同的接口的成功标识和失败提示是不一致的。
   另外，不同的项目的处理方法也是不一致的，这里出错就是简单的alert
   */
  filterNull: function (o) {
    for (let key in o) {
      if (o[key] === null) {
        delete o[key]
      }
      if (this.toType(o[key]) === 'string') {
        o[key] = o[key].trim()
      } else if (this.toType(o[key]) === 'object') {
        o[key] = this.filterNull(o[key])
      } else if (this.toType(o[key]) === 'array') {
        o[key] = this.filterNull(o[key])
      }
    }
    return o
  },

  /**
   * @deprecated
   * @param url
   * @param params
   * @param data
   * @returns {*|Promise<unknown>}
   */
  $get: function (url, params, data) {
    return this.$apiAxios('GET', url, params, data)
  },
  /**
   * @deprecated
   * @param url
   * @param params
   * @param data
   * @returns {*|Promise<unknown>}
   */
  $post: function (url, params, data) {
    return this.$apiAxios('POST', url, params, data)
  },
  /**
   * @deprecated
   * @param url
   * @param params
   * @param data
   * @returns {*|Promise<unknown>}
   */
  $put: function (url, params, data) {
    return this.$apiAxios('PUT', url, params, data)
  },
  /**
   * @deprecated
   * @param url
   * @param params
   * @param data
   * @returns {*|Promise<unknown>}
   */
  $del: function (url, params, data) {
    return this.$apiAxios('DELETE', url, params, data)
  },
  /**
   * @param url
   * @param params
   * @returns {*|Promise<unknown>}
   */
  $get2: function (url, params) {
    return this.$apiAxios2('GET', url, params)
  },
  /**
   * @param url
   * @param params
   * @returns {*|Promise<unknown>}
   */
  $post2: function (url, params) {
    return this.$apiAxios2('POST', url, params)
  },
  /**
   * @param url
   * @param params
   * @returns {*|Promise<unknown>}
   */
  $put2: function (url, params) {
    return this.$apiAxios2('PUT', url, params)
  },
  /**
   * @param url
   * @param params
   * @returns {*|Promise<unknown>}
   */
  $del2: function (url, params) {
    return this.$apiAxios2('DELETE', url, params)
  }
}
